/*******************************************************************************
 * Copyright (C) 2010 Devin Samarin.
 * 
 * This file is part of the SUIT Toolkit.
 * 
 * The SUIT Toolkit is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * The SUIT Toolkit is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with the SUIT Toolkit.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package suit.ui;

/**
 * Allow a Widget to be scrollable. There are times when you have a Widget which
 * is larger than the area you wish to constrain it to, and the usual way to
 * deal with this is to enhance the Widget with scrollbars. Scrollbars are not
 * currently drawn, but the child is moved around with the touch of a finger.
 * 
 * Kinetic scrolling is planned, but not implemented.
 * 
 * @author Devin Samarin
 * 
 */
public class ScrolledWindow extends Widget {

	private int scrollX = 0;
	private int scrollY = 0;
	private int pointX, pointY;
	private int oldScrollX = 0;
	private int oldScrollY = 0;
	private boolean scrollUpDown;
	private boolean scrollLeftRight;

	private Rectangle childReq;

	/**
	 * Construct a new ScrolledWindow
	 * 
	 * @param scrollUpDown
	 *            allow the user to scroll the Widget up and down
	 * @param scrollLeftRight
	 *            allow the user to scroll the Widget from side to side
	 */
	public ScrolledWindow(boolean scrollUpDown, boolean scrollLeftRight) {
		this.scrollUpDown = scrollUpDown;
		this.scrollLeftRight = scrollLeftRight;
	}

	protected boolean onExpose(Event e) {
		if (children != null) {
			Widget w = ((Widget) children.firstElement());
			childReq = w.getRequisition();
			int childx = allocation.x + borderWidth, childy = allocation.y
					+ borderWidth, childw = allocation.w - borderWidth * 2, childh = allocation.h
					- borderWidth * 2;
			startClip(e.graphics, new Rectangle(childx, childy, childw, childh));
			w.sizeAllocate(new Rectangle(childx
					- (scrollLeftRight ? scrollX : 0), childy
					- (scrollUpDown ? scrollY : 0),
					scrollLeftRight ? childReq.w : childw,
					scrollUpDown ? childReq.h : childh));
			w.registerEvent(e);
			endClip(e.graphics);
		}
		return true;
	}

	protected boolean onPointerPressed(Event e) {
		if ((e = localizeEvent(e)) != null) {
			pointX = e.x;
			pointY = e.y;
			oldScrollX = scrollX;
			oldScrollY = scrollY;
		}
		return true;
	}

	protected boolean onPointerDragged(Event e) {
		if ((e = localizeEvent(e)) != null) {
			int deltaX = e.x - pointX;
			int deltaY = e.y - pointY;
			scrollX = Math.max(Math.min(oldScrollX - deltaX, childReq.w
					- allocation.w + borderWidth * 2), 0);
			scrollY = Math.max(Math.min(oldScrollY - deltaY, childReq.h
					- allocation.h + borderWidth * 2), 0);
			invalidate(this);
		}
		return false;
	}

	Rectangle getRequisition() {
		return ((Widget) children.firstElement()).getRequisition();
	}

	/**
	 * Set the scrollbar policy for the scrolling horizontally or vertically.
	 * 
	 * @param scrollUpDown
	 *            whether or not the user can scroll vertically
	 * @param scrollLeftRight
	 *            whether or not the user can scroll horizontally
	 */
	public void setPolicy(boolean scrollUpDown, boolean scrollLeftRight) {
		if (!scrollUpDown) {
			scrollY = 0;
		}
		if (!scrollLeftRight) {
			scrollX = 0;
		}
		this.scrollUpDown = scrollUpDown;
		this.scrollLeftRight = scrollLeftRight;
		invalidate(this);
	}

}
